package com.pgytesting.secondhandcar.util;

import com.alibaba.fastjson.JSONObject;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.pgytesting.secondhandcar.vo.Parameters;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class UtilMethod {


    private static final Double INTEREST = 0.12;

    private static final Double PENALTY_INTEREST = 0.15;


    /**
     * @param @param
     * @return @return
     * @throws
     * @Title: MapToJson
     * @Description: TODO(Map转json对象)
     * @author sunbo@pgytesting.cn
     * @date 2019/5/6 17:49
     */
    public static JSONObject MapToJson(Map param) {
        return new JSONObject(param);
    }


    /**
     * @param @param
     * @return @return
     * @throws
     * @Title: JsonToString
     * @Description: TODO(json转换为字符串)
     * @author sunbo@pgytesting.cn
     * @date 2019/5/6 17:52
     */
    public static String JsonToString(JSONObject param) {
        return param.toJSONString();
    }

    /**
     * @param @param
     * @return @return
     * @throws
     * @Title: JsonToMap
     * @Description: TODO(json对象转换为map)
     * @author sunbo@pgytesting.cn
     * @date 2019/5/6 17:53
     */
    public static Map JsonToMap(JSONObject param) {
        return param;
    }


    /**
     * @param @param
     * @return @return
     * @throws
     * @Title: StringToJson
     * @Description: TODO(字符串转换json对象)
     * @author sunbo@pgytesting.cn
     * @date 2019/5/6 17:54
     */
    public static JSONObject StringToJson(String param) {
        return JSONObject.parseObject(param);
    }

    /**
     * @param @return 设定文件
     * @return String    返回类型
     * @throws
     * @Title: randomCode
     * @Description: TODO(每次调用生成一个6位随机数)
     */
    public static String randomCode() {
        Random rand = new Random();
        int randNumber = rand.nextInt(1000000 - 100000 + 1) + 100000;
        return String.valueOf(randNumber);
    }

    /**
     * @param @return 设定文件
     * @return Long    返回类型
     * @throws
     * @Title: unixString
     * @Description: TODO(获取系统当前时间戳)
     */
    public static Long unixLong() {
        return System.currentTimeMillis();
    }

    /**
     * @param @return 设定文件
     * @return String    返回类型
     * @throws
     * @Title: getdingdan
     * @Description: TODO(生成唯一识别的流水号)
     */
    public static String getdingdan() {
        Date date = new Date();
        SimpleDateFormat sf;
        sf = new SimpleDateFormat("yyyyMMdd");
        return sf.format(date);
    }


    /**
     * @param @return 设定文件
     * @return String    返回类型
     * @throws
     * @Title: getdingdan
     * @Description: TODO(获取当前时间)
     */
    public static String getTime() {
        Date date = new Date();
        SimpleDateFormat sf = new SimpleDateFormat();
        sf = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
        return sf.format(date);
    }

    /**
     * 获取每天0:0:0秒的时间戳
     *
     * @return
     */
    public static Long getTodayZero() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH),
                0, 0, 0);
        Date beginOfDate = calendar.getTime();
        return beginOfDate.getTime();
    }

    /**
     * 获取每天23:59:59的时间戳
     *
     * @return
     */
    public static Long getTodayLastMinute() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH),
                23, 59, 59);
        Date endOfDate = calendar.getTime();
        return endOfDate.getTime();
    }

    /**
     * @param @return 设定文件
     * @return String    返回类型
     * @throws
     * @Title: getUnixToTime
     * @Description: TODO(时间戳转换为时间)
     */
    public static String getUnixToTime(Long date) {
        SimpleDateFormat sf = new SimpleDateFormat();
        sf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
        return sf.format(date);
    }

    /**
     * 获取年
     *
     * @param date
     * @return
     */
    public static String getUnixToYear(Long date) {
        SimpleDateFormat sf = new SimpleDateFormat();
        sf = new SimpleDateFormat("yyyy");
        return sf.format(date);
    }

    /**
     * 获取月
     *
     * @param date
     * @return
     */
    public static String getUnixToMonth(Long date) {
        SimpleDateFormat sf = new SimpleDateFormat();
        sf = new SimpleDateFormat("MM");
        return sf.format(date);
    }

    /**
     * 获取天
     *
     * @param date
     * @return
     */
    public static String getUnixToDay(Long date) {
        SimpleDateFormat sf = new SimpleDateFormat();
        sf = new SimpleDateFormat("dd");
        return sf.format(date);
    }


    /**
     * 时间转换为时间戳
     *
     * @param time
     * @return
     */
    public static Long getTimeToUnix(String time) {
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = null;
        try {
            date = sf.parse(time);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date.getTime();
    }

    /**
     * @param @return 设定文件
     * @return String    返回类型
     * @throws
     * @Title: uuidMd5Encryption
     * @Description: TODO(生成唯一标识的UUID)
     */
    public static String getUniqueCode() {
        return String.valueOf(UUID.randomUUID());
    }


    /**
     * @param @return 设定文件
     * @return String    返回类型
     * @throws
     * @Title: md5Encryption
     * @Description: TODO(32位加密加盐方法)
     */
    public static String md5Encryption(String passWord) {
        try {
            // 得到一个信息摘要器
            MessageDigest digest = MessageDigest.getInstance("md5");
            byte[] result = digest.digest(passWord.getBytes());
            StringBuffer buffer = new StringBuffer();
            // 把每一个byte 做一个与运算 0xff;
            for (byte b : result) {
                // 与运算
                int number = b & 0xff;// 加盐
                String str = Integer.toHexString(number);
                if (str.length() == 1) {
                    buffer.append("0");
                }
                buffer.append(str);
            }
            // 标准的md5加密后的结果
            return buffer.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * @param @param  unix
     * @param @return 设定文件
     * @return String    返回类型
     * @throws
     * @Title: getSecondToTime
     * @Description: TODO(将秒转换为时间)
     */
    public static String getSecondToTime(Long unix) {
        Long unix1;
        Long unix2;
        unix1 = unix / 60;
        unix2 = unix1 / 60;
        log.info("执行转换方法：将" + unix + "秒转换为" + unix2 + ":" + unix1 % 60 + ":" + unix % 60);
        StringBuffer time = new StringBuffer();
        if (unix >= 3600) {
            time.append(unix2 + ":");
        }
        if (unix >= 60) {
            time.append(unix1 % 60 + ":");
        }
        return String.valueOf(time.append(unix % 60));
    }


    /**
     * 利用正则表达式判断字符串是否是数字
     *
     * @param str
     * @return
     */
    public static boolean isNumeric(String str) {
        Pattern pattern = Pattern.compile("[0-9]*");
        Matcher isNum = pattern.matcher(str);
        if (!isNum.matches()) {
            return false;
        }
        return true;
    }


    /**
     * @param @param  num
     * @param @return 设定文件
     * @return double    返回类型
     * @throws
     * @Title: getTwoDecimal
     * @Description: TODO(保留两位小数 ， 四舍五入)
     */
    public static Double getTwoDecimal(Double num) {
        DecimalFormat dFormat = new DecimalFormat("#.00");
        String yearString = dFormat.format(num);
        Double temp = Double.valueOf(yearString);
        return temp;
    }


    /**
     * 获得该月最后一天
     *
     * @param year
     * @param month
     * @return
     */
    public static String getLastDayOfMonth(int year, int month) {
        Calendar cal = Calendar.getInstance();
        //设置年份
        cal.set(Calendar.YEAR, year);
        //设置月份
        cal.set(Calendar.MONTH, month - 1);
        //获取某月最大天数
        int lastDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
        //设置日历中月份的最大天数
        cal.set(Calendar.DAY_OF_MONTH, lastDay);
        //格式化日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String lastDayOfMonth = sdf.format(cal.getTime());
        return lastDayOfMonth;
    }


    /**
     * @param @param 至少银行卡前六位
     * @return @return Map<String,Object>
     * @throws
     * @Title: getBackCardInf
     * @Description: TODO(读取json文件对银行卡进行银行卡信息查询)
     * @author sunbo@pgytesting.cn
     * @date 2019/5/8 22:02
     */
    public static Map<String, Object> getBackCardInf(String backNumber) {
        if (backNumber.length() < 6) {
            return null;
        }
        JsonObject jsonObject = getReadJson();
        JsonObject jsonObject2 = (JsonObject) (backNumber.length() == 6 ? jsonObject.get(backNumber) : jsonObject.get(backNumber.substring(0, 6)));
        Map<String, Object> resultMap = new LinkedHashMap<>();
        log.info("进行银行信息填入");
        resultMap.put("bankCardNo", backNumber);
        if (jsonObject2 != null) {
            resultMap.put("bankName", jsonObject2.get("issuer").getAsString());
            resultMap.put("bankCode", jsonObject2.get("issuerCode").getAsString());
//            resultMap.put("cardName",jsonObject2.get("cardName").getAsString());
            resultMap.put("cardType", jsonObject2.get("bankCardType").getAsString().equals("借记卡") ? 1 : 2);
//            resultMap.put("length",jsonObject2.get("length").getAsInt());
        } else {
            resultMap.put("cardType", "UNKNOW");
            resultMap.put("bankName", "");
            resultMap.put("bankCode", "");
        }
        return resultMap;
    }

    /**
     * @param @param 至少银行卡前六位
     * @return @return Map<String,Object>
     * @throws
     * @Title: getBackCardList
     * @Description: TODO(读取json文件对银行卡进行银行卡信息查询)
     * @author sunbo@pgytesting.cn
     * @date 2019/5/8 22:02
     */
    public static List<Map<String, Object>> getBackCardList() {
        log.info("获取到json文本的数据");
        JsonObject jsonObject = getReadJson();
        Map<String, Object> map = new HashMap<>();
        log.info("对数据进行去重处理");
        for (String s : jsonObject.keySet()) {
            String key = jsonObject.getAsJsonObject(s).get("issuerCode").getAsString();
            String values = jsonObject.getAsJsonObject(s).get("issuer").getAsString();
            if (isNumeric(key) && StringUtils.isEmpty(key)) {
                continue;
            }
            map.put(key, values);
        }
        log.info("对数据进行最终迭代");
        List<Map<String, Object>> resultList = new LinkedList<>();
        for (String s : map.keySet()) {
            Map<String, Object> reultMap = new HashMap<>();
            reultMap.put("bankCode", s);
            reultMap.put("bankName", map.get(s));
            resultList.add(reultMap);
        }
        return resultList;
    }


    /**
     * @return @return com.google.gson.JsonObject
     * @throws
     * @Title: getReadJson
     * @Description: TODO(进行json文件读取)
     * @author sunbo@pgytesting.cn
     * @date 2019/5/23 19:57
     */
    public static JsonObject getReadJson() {
        JsonParser jsonParser = new JsonParser();
        JsonObject jsonObject;
        try {
            log.info("进行静态数据文件的绝对路径获取");
            String jsonFilePath = Thread.currentThread().getContextClassLoader().getResource("").getPath() + "json/BackCardBin.json";
            log.info("获取到的路径为：" + jsonFilePath);
            log.info("进行银行信息数据格式化为json");
            jsonObject = (JsonObject) jsonParser.parse(new FileReader(jsonFilePath));
        } catch (Exception e) {
            log.error("BackCardBin.json文件读取异常");
            return null;
        }
        return jsonObject;
    }

    /**
     * @param @param json文件的名称
     * @return @return com.alibaba.fastjson.JSONObject
     * @throws IOException
     * @Title: getReadJSONObject
     * @Description: TODO(读取json文件返回JSONObject)
     * @Author frosty0804@gmail.com
     * @User: frosty
     * @date 2019/6/11 9:29
     */
    public static JSONObject getReadJSONObject(String fileName) throws IOException {
        File jsonFile = ResourceUtils.getFile("classpath:" + fileName);
        String json = FileUtils.readFileToString(jsonFile, "utf-8");
        return JSONObject.parseObject(json);
    }


    /**
     * 获取公钥私钥，并生成系统时间
     *
     * @return
     */
    public static Map<String, String> getKey() {
        log.info("公钥私钥为空，则进行公钥私钥生成");
        Map<String, String> keyMap = new HashMap<>();
        try {
            keyMap = RSAUtils.createKeys();
            keyMap.put("systemUnixTime", UtilMethod.unixLong().toString());
            log.info("公钥私钥获取成功");
        } catch (Exception e) {
            log.info("获取公钥私钥异常" + e.getMessage());
        }
        return keyMap;
    }


    /**
     * 验证银行卡
     *
     * @param cardNo 银行卡号
     * @return
     */
    public static boolean matchLuhn(String cardNo) {
        try {
            int[] cardNoArr = new int[cardNo.length()];
            for (int i = 0; i < cardNo.length(); i++) {
                cardNoArr[i] = Integer.valueOf(String.valueOf(cardNo.charAt(i)));
            }
            for (int i = cardNoArr.length - 2; i >= 0; i -= 2) {
                cardNoArr[i] <<= 1;
                cardNoArr[i] = cardNoArr[i] / 10 + cardNoArr[i] % 10;
            }
            int sum = 0;
            for (int i = 0; i < cardNoArr.length; i++) {
                sum += cardNoArr[i];
            }
            return sum % 10 == 0;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 驾驶证验证
     *
     * @param driversLicenseModel 驾驶证型号
     * @return
     */
    public static Boolean checkDriversLicenseModel(String driversLicenseModel) {
        for (String s : Parameters.DRIVER_LICENSE_MODEL) {
            if (s.equals(driversLicenseModel)) {
                return Boolean.TRUE;
            }
        }
        return Boolean.FALSE;
    }

    /**
     * 检查学历
     *
     * @param education 学历ID
     * @return
     */
    public static Boolean checkEducation(String education) {
        for (String s : Parameters.EDUCATION) {
            if (s.equals(education)) {
                return Boolean.TRUE;
            }
        }
        return Boolean.FALSE;
    }

    /**
     * 检查联系人关系
     *
     * @param relationship 学历ID
     * @return
     */
    public static Boolean checkRelationship(String relationship) {
        for (String s : Parameters.RELATIONSHIP) {
            if (s.equals(relationship)) {
                return Boolean.TRUE;
            }
        }
        return Boolean.FALSE;
    }

    /**
     * 获取某年有多少天
     *
     * @param year 年
     * @return
     */
    public static Integer getYearDay(Integer year) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, year);
        return calendar.getActualMaximum(Calendar.DAY_OF_YEAR);
    }

    /**
     * 获取某年某月有多少天
     *
     * @param year  年
     * @param month 月
     * @return
     */
    public static Integer getMonthDay(Integer year, Integer month) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month);
        return calendar.getActualMaximum(Calendar.DATE);
    }

    /**
     * 获取今年某月有多少天
     *
     * @param month 月
     * @return
     */
    public static Integer getMonthDay(Integer month) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, Calendar.YEAR);
        calendar.set(Calendar.MONTH, month);
        return calendar.getActualMaximum(Calendar.DATE);
    }


    /**
     * 计算贷款金额每月还款额
     *
     * @param amount 本金
     * @param year   还款年限
     * @return
     */
    public static Double accountingInterest(Double amount, Integer year) {
        return getTwoDecimal(amount * INTEREST / (year * 12) +
                (amount / (year * 12)));
    }


    /**
     * 计算罚息
     *
     * @param amount 还款额
     * @param day    逾期天数
     * @return
     */
    public static Double penaltyInterest(Double amount, Integer day) {
        // 计算本年有多少天
        return amount * PENALTY_INTEREST / getYearDay(Calendar.YEAR) * day;
    }


    /**
     * 获取每月开始时间的时间戳
     *
     * @return
     */
    public static Long startMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MONTH, 0);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTimeInMillis();
    }


}
